/* EquityGraph */
import { Algorithm } from '@antv/g6';
import Graphin, { Behaviors, G6, GraphinContext } from '@antv/graphin';
import { useEventEmitter, useRequest, useUpdateEffect } from '@umijs/hooks';
import { useContext, useEffect, useState, createRef } from 'react';
/* 数据来源 */
import { OptionToolbarTwo } from '@/components/Toolbar';
import { getEnterprisesDetails } from '@/services/zhirong/enterprise';
import { getEquityNetwork, getRelationNetwork } from '@/services/zhirong/equity';
import ProCard from '@ant-design/pro-card';
import { Tooltip } from '@antv/graphin-components';
import iconLoader from '@antv/graphin-icons';
import '@antv/graphin-icons/dist/index.css';
import { Card, Collapse, message, Select, Tag, Typography } from 'antd';
import CompanyInfo from '@/pages/MultiQuery/components/companyInfo';
import MiniMap from './MiniMap'

const { ZoomCanvas, FontPaint, ActivateRelations, DragNodeWithForce, FitView } = Behaviors;

const { fontFamily } = iconLoader();
const icons = Graphin.registerFontFamily(iconLoader);

const { Option } = Select;
const { Meta } = Card;
const { Panel } = Collapse;
const { Title } = Typography;

const EDGE_HIGHLIGHT_KEYSHAPE = {
  fill: 'red',
  stroke: 'red',
  lineWidth: 2,
};
const EDGE_NORMAL_KEYSHAPE = {
  fill: '#999',
  stroke: '#999',
  lineWidth: 1,
};
/* https://g6.antv.vision/zh/docs/api/Algorithm#findallpathgraphdata-start-end-directed 查找两点之间的所有路径 */
const { findAllPath } = Algorithm;

//高亮路径行为组件
const HighlightAllPath = (props) => {
  const { graph, apis } = useContext(GraphinContext);

  useEffect(() => {
    graph.on('node:mouseenter', handleMouseEnter);
    graph.on('node:mouseleave', handleMouseLeave);
    return () => {
      graph.off('node:mouseenter', handleMouseEnter);
      graph.off('node:mouseleave', handleMouseLeave);
    };
  }, []);
  useEffect(() => {
    console.log('当前中心结点eid为：', props.centerId);
  }, [props.centerId]);

  const getAllPath = (node, center) => {
    const data = graph.cfg.data;
    const allPath = findAllPath(data, node, center);
    return allPath;
  };
  const handleMouseEnter = (evt) => {
    const node = evt.item;
    const model = node.getModel();
    console.log(props.centerId);
    const paths = getAllPath(model.id, props.centerId);
    const path = paths[0];
    console.log(path);
    try {
      for (let i = 0; i < path?.length - 1; i++) {
        const edge = graph.find('edge', (edge) => {
          // 巨坑，如果用let定义edge的话，即使找到符合条件的edge也会返回undefine
          return edge.getModel().source === path[i] && edge.getModel().target === path[i + 1];
        });
        console.log(edge);
        const model = edge?.getModel();
        const { style } = model;
        graph.updateItem(edge, {
          ...model,
          style: {
            ...style,
            keyshape: EDGE_HIGHLIGHT_KEYSHAPE,
          },
        });
      }
    } catch (error) {
      console.log("Find error in handleMouseEnter, while changing paths' style, details:", error);
    }
  };

  const handleMouseLeave = (evt) => {
    const node = evt.item;
    const model = node.getModel();
    const paths = getAllPath(model.id, props.centerId);
    const path = paths[0];
    try {
      for (let i = 0; i < path?.length - 1; i++) {
        const edge = graph.find('edge', (edge) => {
          return edge.getModel().source === path[i] && edge.getModel().target === path[i + 1];
        });
        const model = edge?.getModel();
        const { style } = model;
        graph.updateItem(edge, {
          ...model,
          style: {
            ...style,
            keyshape: EDGE_NORMAL_KEYSHAPE,
          },
        });
      }
    } catch (error) {
      console.log("Find error in handleMouseLeave, while changing paths' style, details:", error);
    }
  };

  return null;
};

// topk路径面板
/* const HightlightTopkPathPanel = (props) => {
  const { graph, apis } = useContext(GraphinContext);
  const [currentNode, setCurrentNode] = useState(null);
  const [pathList, setPathList] = useState([]);
  const { findAllPath } = Algorithm; // 以后替换为topk路径接口
  useEffect(() => {
    const _pathList = currentNode ? getAllPath(currentNode.getModel().id) : [];
    setPathList(_pathList);
  }, [currentNode]);
  props.nodeSelect$.useSubscription(() => {
    getSelectedNode();
  });
  const getSelectedNode = (evt) => {
    const selectedNodes = graph.findAllByState('node', 'selected');
    setCurrentNode(selectedNodes[0]);
    console.log('selectedNode: ', selectedNodes);
  };
  const getAllPath = (node) => {
    const { data } = graph.cfg;
    const allPath = findAllPath(data, node, props.centerId, true);
    // console.log('allPath:', allPath, node, props.centerId)
    return allPath;
  };
  const PathItems = (props) => {
    const items = props.pathList.map((path) => {
      // console.log(path)
      return <Path key={path} path={path} />;
    });
    return <>{items}</>;
  };
  const Path = (props) => {
    const path = props.path;
    const [isHovering, hoverRef] = useHover({
      onEnter: () => {
        for (let i = 0; i < path?.length - 1; i++) {
          const edge = graph.find('edge', (edge) => {
            // 巨坑，如果用let定义edge的话，即使找到符合条件的edge也会返回undefine
            return edge.getModel().source === path[i] && edge.getModel().target === path[i + 1];
          });
          try {
            const model = edge.getModel();
            const { style } = model;
            graph.updateItem(edge, {
              ...model,
              style: {
                ...style,
                keyshape: EDGE_HIGHLIGHT_KEYSHAPE,
              },
            });
          } catch (error) {
            console.log(
              "Error occurs onEnter <Path/> , while changing paths' style, details:",
              error,
            );
          }
        }
      },
      onLeave: () => {
        for (let i = 0; i < path?.length - 1; i++) {
          const edge = graph.find('edge', (edge) => {
            return edge.getModel().source === path[i] && edge.getModel().target === path[i + 1];
          });
          try {
            const model = edge.getModel();
            const { style } = model;
            graph.updateItem(edge, {
              ...model,
              style: {
                ...style,
                keyshape: EDGE_NORMAL_KEYSHAPE,
              },
            });
          } catch (error) {
            console.log(
              "Error occurs onLeave <Path/> , while changing paths' style, details:",
              error,
            );
          }
        }
      },
    });
    const NameList = () => {
      const tags = path.map((id) => {
        const node = graph.findById(id);
        return (
          <Tag key={id + new Date().getTime()}>{node ? node.getModel().name : 'undefined'}</Tag>
        );
      });
      return <>{tags}</>;
    };
    return (
      <p style={{ cursor: 'pointer' }} ref={hoverRef}>
        <NameList />
      </p>
    );
  };
  return (
    <Collapse
      style={{ width: '320px', position: 'absolute', top: '0px', left: '0px', zIndex: 10 }}
      // defaultActiveKey={['topk']}
      expandIcon={({ isActive }) => <CaretRightOutlined rotate={isActive ? 90 : 0} />}
    >
      <Panel header="Top-k持股路径" key="topk">
        {currentNode ? (
          <>
            <Title level={5}>{currentNode.getModel().name}</Title>
            <PathItems pathList={pathList} />
          </>
        ) : (
          <Empty />
        )}
      </Panel>
    </Collapse>
  );
}; */
//用于监听选择节点行为，触发更新面板事件
const NodeSelectBehavior = (props) => {
  const { graph, apis } = useContext(GraphinContext);

  useEffect(() => {
    graph.on('nodeselectchange', handleNodeSelectChange);
    return () => {
      graph.off('nodeselectchange', handleNodeSelectChange);
    };
  }, []);

  const handleNodeSelectChange = (evt) => {
    props.nodeSelect$.emit();
    // console.log(evt)
  };
  return null;
};
const defaultNodeStatusStyle = {
  status: {
    hover: {
      halo: {
        visible: false,
      },
    },
  },
};


const NodeDetailTip = (props) => {
  const [CompanyInfo, setCompanyInfo] = useState({})
  const { tooltip } = useContext(GraphinContext);
  const context = tooltip.node;
  const { item } = context;
  const model = item && item.getModel();
  const [nodeDetail, setNodeDetail] = useState({});
  // console.log(`来自NodeDetailTip组件，目前结点${model.id}被hover`, model);


  /* 获取card的详细信息 */
  const { loading, run: runGetEnterprisesDetails, } = useRequest(getEnterprisesDetails, {
    manual: true,
    onSuccess: (result, params) => {
      if (result && result.code === 200) {
        console.log("detail result", result);
        setCompanyInfo(result.data[0])
        setNodeDetail(result.data[0]);
      } else if (result.code === 666) {
        message.info('未找到该实体详细信息.');
      } else {
        message.error('获取实体详情失败！');
      }
    },
    onError: (err, params) => {
      console.log('Error detail: ', err);
      console.log('params: ', params);
      message.error('数据请求错误！');
    },
  });

  useEffect(() => {
    console.log('h.212121', model);
    if (model.category === '' || model.category === 'E') {
      runGetEnterprisesDetails({
        company_name: model.name,
        ts: new Date().getTime(),
      });
    } else {
      console.log('hovering node is person.');
    }
    return () => { };
  }, [runGetEnterprisesDetails, model.category]);



  return (
    // @ts-ignore
    <div>
      {model.category === '' || model.category === 'E' ? (
        <Card
          title={
            <>
              {CompanyInfo.FullName ? CompanyInfo.FullName : nodeDetail.FullName}
              <br />
              {String(nodeDetail?.Status).indexOf('存续') !== -1 && <Tag color="blue">存续</Tag>}
              {String(nodeDetail?.Status).indexOf('注销') !== -1 && <Tag color="orange">注销</Tag>}
              {String(nodeDetail?.Status).indexOf('迁出') !== -1 && <Tag color="orange">迁出</Tag>}
              {String(nodeDetail?.Status).indexOf('吊销') !== -1 && <Tag color="red">吊销</Tag>}
            </>
          }
          style={{ width: '300px' }}
          loading={loading}
        >
          法定代表人：{nodeDetail?.LegalRepresentative}
          <br />
          注册单位：{nodeDetail?.OfficeAddress}
          <br />
          {/* 注册资本：{Number(nodeDetail?.RegisterCapital / 10000).toFixed(2)}万元 */}
          注册资本：{nodeDetail?.RegisterCapital}
          <br />
          社会统一信用代码：{nodeDetail?.SocialCreditCode}
        </Card>
      ) : (
        <Card title={model?.name}></Card>
      )}
    </div>
  );
};

const TimeBar = (props) => {
  const { graph } = useContext(GraphinContext);
  console.log("props", props);
  const timeBarData = [];
  for (let i = 0; i < 100; i++) {
    timeBarData.push({
      date: `2020${i}`,
      value: Math.round(Math.random() * 300),
    });
  }
  useEffect(() => {
    const width = graph.getWidth();
    const height = graph.getHeight();
    const timeBarOptions = {
      x: 0,
      y: 0,
      width,
      height: 100,
      padding: 10,
      type: 'simple',
      trend: {
        data: timeBarData,
      },
    };
    const timeBar = new G6.TimeBar(timeBarOptions);
    graph.addPlugin(timeBar);
    return () => {
      if (timeBar && !timeBar.destroy) {
        graph.removePlugin(timeBar);
      }
    };
  }, []);
  return null;
};

const EquityGraph = (props) => {
  const date = props.date;
  // 存储本页面自己的date
  const [myDate, setMyDate] = useState(date);
  // 判断是否自动演化
  const [isAuto, setIsAuto] = useState(false);
  // 用于存储股权网络的请求数据以免被控制权覆盖
  const [stockNetwork, setStockNetwork] = useState();
  const [enterpriseId, setEnterpriseId] = useState(props.eid);
  const [type, setType] = useState(props.type);

  const [height, setheight] = useState(props.height);

  // 用于更新图的数据，取值会根据 股权or控制权 发生变化
  const [network, setNetwork] = useState({
    nodes: [
      {
        name: '招商银行股份有限公司',
        id: '001',
        label: '招商银行股份有限公司',
        x: 100,
        y: 100,
        // type: 'rect',
      },
    ],
    edges: [],
    combo: undefined,
  });

  const { loading, run } = useRequest(getEquityNetwork, {
    manual: true,
    onSuccess: (result) => {
      // console.log("result", result);
      dataProcess(result.data);
      setStockNetwork(result.data);
      // console.log("equityNetwork:", network) // obviously, the output is still []~
      // props.onNetworkChange(network) // 经过测试通过setNetwork更改的状态并不能马上生效，所以状态提升操作不能放在这里，应该移至useEffect
    },
  });

  const { run: runRelation } = useRequest(getRelationNetwork, {
    manual: true,
    onSuccess: (result) => {
      console.log("result", result);
      dataProcess(result.data);
      setStockNetwork(result.data);
      // console.log("equityNetwork:", network) // obviously, the output is still []~
      // props.onNetworkChange(network) // 经过测试通过setNetwork更改的状态并不能马上生效，所以状态提升操作不能放在这里，应该移至useEffect
    },
  });

  useEffect(() => {
    run({
      centerId: enterpriseId,
      tStart: "2022-02-16",
      tEnd: "2022-05-16",
      direction: 1,
      level: 10,
    });



  }, [enterpriseId]);

  // useUpdateEffect(() => {
  //   if(date){
  //     dataProcess(stockNetwork)

  //   }
  //   //  const { links } = stockNetwork;
  //   //  let edges = links.filter((edge) => edge.tstart < date);
  //   //  setNetwork({...stockNetwork,edges});
  // },[date])

  useUpdateEffect(() => {
    // 通过date筛选不同的数据在dataProcess函数里
    console.log("date一一一", date);
    console.log("props.network", props.network);
    if (date === "2018" && !isAuto) {
      setIsAuto(true);
      autoPlay(date);
    }
    if (props.network) {
      dataProcess(props.network);
    } else if (stockNetwork) {
      console.log("rerender", stockNetwork);
      dataProcess(stockNetwork)
    }
  }, [props.network, date, myDate]);

  const autoPlay = (date) => {
    console.log("date的值是", date);
    const i = setInterval(() => {
      date = "" + (parseInt(date) + 1)
      console.log(date);
      setMyDate(date);
      if (date === "2022" || date == NaN) {
        clearInterval(i);
        setIsAuto(false);
      }
    }, 3000);
  }

  useUpdateEffect(() => {
    setEnterpriseId(props.eid);
  }, [props.eid]);

  useUpdateEffect(() => {
    console.log('equityNetwork:', network);
    setNetwork(network);
    props.onNetworkChange(network);
  }, [network]);

  // 处理数据，为节点和边添加样式
  const dataProcess = (data) => {
    const idSets = new Set();
    let isControl = false;
    if (props.network) {
      isControl = true;
      console.log('从props里拿', data);
      data = data.data;
      data.nodes.forEach((node) => {
        idSets.add(node.id);
      });
    } else {
      ComputeFinalHolders(data).forEach((item) => {
        idSets.add(item.id);
      });
    }
    let { nodes, links, stat, plots } = isControl ? data.relations : data;
    const percentRank = [];
    nodes.forEach((node) => {
      // 判断节点是否需要高亮
      const flag = idSets.has(node.id);
      //节点样式
      // node.type = 'rect',  //改成方形
      percentRank.push(node.percent);
      percentRank.sort(function (a, b) {
        return a - b;
      });
      const top10Percent = percentRank.slice(0, 9);

      node.style = {
        icon: {
          fontFamily,
          type: 'font',
          value: node.category === '自然人' ? icons.user : icons.company,
          fill:
            node.id === enterpriseId ? 'red' : flag ? isControl ? '#17DCA7' : 'pink' : '#1890ff',
          size: node.id === enterpriseId ? 20 : flag ? 18 : 15,
          fillOpacity: 0.8,
          // value: icons.home
        },
        keyshape: {
          size: node.id === enterpriseId ? 45 : flag ? 35 : 25,
          fill:
            node.id === enterpriseId ? 'red' : flag ? isControl ? '#17DCA7' : 'pink' : '#1890ff',
          stroke:
            node.id === enterpriseId ? 'red' : flag ? isControl ? '#17DCA7' : 'pink' : '#1890ff',
          fillOpacity: 0.2,
        },
        label: {
          value: node.name,
          offset: [0, 20],
          fontSize: top10Percent.indexOf(node.percent) ? 12 : 12,
        },
      };
      node.label = node.name;
    });
    // 通过不同的时间节点进行筛选数据
    if (date && !isAuto) { links = links.filter((edge) => edge.tstart < date); }
    if (isAuto) { links = links.filter((edge) => edge.tstart < myDate); }
    links.forEach((edge) => {
      edge.style = {
        keyshape: {
          fill: '#999',
          stroke: '#999',
          lineWidth: 0.7,
          type: edge.target === edge.source ? 'loop' : 'string',
        },
        label: {
          value: `持股${(edge.value * 100).toFixed(2)}%`,
          fill: '#722ED1',
          fontSize: 10,
        },
      };
    });

    setNetwork({ ...network, nodes, edges: links, plots, stat }); // setNetwork在这里可能是异步执行的？
    // console.log("network: ", network) //更改之后的network并不能在这里log出来，所以这里log的结果还是[]
  };
  // 计算右侧展示的节点信息
  const ComputeFinalHolders = (network) => {
    const { nodes, links } = network;
    const finalHolders = nodes?.map((node) => {
      return {
        ...node,
        inDegree: 0,
        outDegree: 0,
      };
    });
    links?.forEach((edge) => {
      finalHolders.forEach((node) => {
        if (node.id === edge.source) {
          node.outDegree += 1;
        }
        if (node.id === edge.target) {
          node.inDegree += 1;
        }
      });
    });
    return finalHolders?.filter((node) => node.inDegree === 0);
  };

  const { DragCanvas } = Behaviors;

  const layout = {
    type: 'dagre',
    rankdir: 'BT',
    minMovement: 0.01,
    maxIteration: 5000,
    preventOverlap: true,
    damping: 0.99,
  };

  const shouldBegin = () => {
    return true;
  };

  const nodeSelect$ = useEventEmitter();

  return (
    <ProCard loading={loading} ghost style={{ height: height ? height : '85vh' }}>
      {network.nodes?.length > 0 && (
        <Graphin data={network} layout={layout} FitView="true"
        >
          {/* <Select defaultValue="2018" style={{ width: 120, position: 'absolute', top: 0 }}>
      <Option value="2017">2017</Option>
      <Option value="2018">2018</Option>
      <Option value="2019">2019</Option>
    </Select> */}
          {/*    <HightlightTopkPathPanel nodeSelect$={nodeSelect$} centerId={enterpriseId} /> */}
          <NodeSelectBehavior nodeSelect$={nodeSelect$} />
          <DragNodeWithForce autoPin={true} />

          <FontPaint />
          <DragCanvas shouldBegin={shouldBegin} />
          <ZoomCanvas />
          <Tooltip bindType="node">
            <NodeDetailTip />
          </Tooltip>
          <OptionToolbarTwo direction={'horizontal'} refresh={props.refresh} />
          <HighlightAllPath centerId={enterpriseId} />
          {/* <TimeBar options={"123"} /> */}

          {/* <MiniMap /> */}

        </Graphin>
      )}
    </ProCard>
  );
};

export default EquityGraph;